﻿using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using distrilan;
using System.IO;


public partial class admin_Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //se nella sessione non c'e utente amministratore, redirigo l'utente alla pagina di login
        if (SiteUser.IsLoggedAdmin() == false)
            Server.Transfer("index.aspx");

        btnEliminaArticoli.Attributes.Add("onclick", "ShowHideCaricamento('visible');");
    }

    /// <summary>
    /// crea un elenco contenente le cartelle da eliminare dal disco
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnElencoArticoliEliminare_Click(object sender, EventArgs e)
    {
        String directoryArticoli = "../" + ConfigurationManager.AppSettings["dir_articoli"].ToString();
        directoryArticoli = Server.MapPath(directoryArticoli);
        String[] directories = Directory.GetDirectories(directoryArticoli);
        int articoliEliminati = 0;
        //ArrayList articoliEliminati = new ArrayList(); 

        //prendo tutte le directory contenute nella cartella degli articoli
        //int indiceUltimoSlash;

        //apro il file di log 
        String nomeFile = "file-log-" + DateTime.Now.ToString().Replace("/","-") + ".txt";
        String pathFileLog = Server.MapPath("log/") + nomeFile;
        StreamWriter writer = new StreamWriter(pathFileLog, true);
        
        foreach (String directory in directories)
        {
            //indiceUltimoSlash = 0;
            
            //questa procedura è piu semplice ma meno funzionale perche scorre tutta la stringa e arriva alla fine
            //la procedura seguente è un pelino + complessa ma è più ottimizzata perche siccome il codice dell'articolo è l'ultima parte, 
            //si prende la stringa partendo dalla fine e poi si fa il reverse della stringa

            //for (int i = 0; i < directory.Length; i++){ 
            //    if(directory[i] == Convert.ToChar("\\"))
            //      indiceUltimoSlash = i;
            //}

            ////qui dovrei sapere qual'è l'indice dell'ultimo slash
            //String codart = directory.Substring(indiceUltimoSlash + 1);

            
            String codart = "";
            char backSlash = Convert.ToChar("\\");
            int lung = directory.Length;
            while (true){
                if (directory[lung-1] == backSlash)
                    break;
                else{
                    codart += directory[lung-1];
                    lung--;
                }
            }
            //effettuo il reverse della stringa
            char[] arr = codart.ToCharArray();
            Array.Reverse(arr);
            codart = new string(arr);

            String query = "SELECT * FROM articolo WHERE codart = '" + codart + "'";
            SqlConnection connection = new SqlConnection(Utility.GetDBConnectionString());
            SqlDataAdapter adapter = new SqlDataAdapter(query, connection);
            DataTable dt = new DataTable();

            try{
                connection.Open();
                adapter.Fill(dt);

                //sollevo l'eccezione se non è un numero di righe possibile
                if (dt.Rows.Count != 1 & dt.Rows.Count != 0)
                    throw new Exception("letto un numero inconsistente di righe");

                //se l'articolo è presente su database non devo fare niente
                //if (dt.Rows.Count == 1)
                //{  }

                //se l'articolo non è più presente su database, allora devo eliminare la cartella
                else if (dt.Rows.Count == 0)
                {
                    //tento l'eliminazione dal database e me la salvo sull'array degli articoli eliminati
                    try{
                        //non elimino i files ma li aggiungo solo a un documento di testo che mi servira poi per eliminare i files
                        //Directory.Delete(directory, true);
                        articoliEliminati++;
                        //articoliEliminati.Add(directory);
                        writer.Write(directory + "\r" + "\n");
                        lblArticoliEliminati.Text += directory + "<br/>";
                    }
                    catch (Exception ex){
                        lblMessage.Text = "ERRORE:" + ex.Message;
                        Utility.WriteLog("ERRORE", "btnEliminaArticoli_Click in eliminaArticoloNoDb.aspx.cs", ex.Message, "", "");
                    }
                }
            }
            catch (Exception ex){
                lblMessage.Text = "ERRORE:" + ex.Message;
                Utility.WriteLog("ERRORE", "btnEliminaArticoli_Click in eliminaArticoloNoDb.aspx.cs", ex.Message, "", "");
                return;
            }
            finally{
                connection.Close();
            }
        }
        //setto le variabili per potere fare effettivamente l'eliminazione da disco
        hfArticoliEliminare.Value = pathFileLog;
        btnEliminaArticoli.Visible = true;

        lblDatiArticoliEliminati.Text = "totale articolo da eliminare = " + articoliEliminati.ToString() + "<br/>";
        linkFileLog.Attributes.Add("href", "log/" + nomeFile);
        linkFileLog.Text = "clicca qui per scaricare il file contenente gli articoli da eliminare";
        linkFileLog.CssClass = "lblAdmin";
        
        //
        //writer.Write("totale articoli da eliminare:" + articoliEliminati.ToString());

        //e svuoto il buffer
        writer.Flush();

        //rilascio tutte le risorse del writer
        writer.Dispose();

    }


    /// <summary>
    /// elimina effettivamente gli articoli da disco
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void eliminaArticoli_Click(object sender, EventArgs e)
    {
        int i = 0;
        StreamReader objReader = null;
        ArrayList arrText = null;
        try
        {
            // Leggo tutte le righe che compongono il file
            objReader = new StreamReader(hfArticoliEliminare.Value);
            String line = "";
            arrText = new ArrayList();
            while (line != null)
            {
                // Se ho letto una line valida 
                line = readLine(objReader);
                if (line != null)
                {
                    try{
                        Directory.Delete(line, true);
                    }
                    catch (Exception ex)
                    {
                        lblMessage.Text = "errore in fase di eliminazione dell'articolo: " + line + "nel file: " + hfArticoliEliminare.Value;
                        Utility.WriteLog("ERRORE", "eliminaArticoli_Click in eliminaArticoliNoDB.cs", "errore in fase di eliminazione dell'articolo: " + line + "nel file: " + hfArticoliEliminare.Value + " errore:" + ex.Message, "", "");
                        return;
                    }
                }
                i++;
            }
            int articoliEliminati = i;
            articoliEliminati--;

            lblArticoliEliminati.Text = "";
            lblDatiArticoliEliminati.Text = "";

            lblMessage.Text = "eliminati: " + articoliEliminati.ToString() + " articoli da disco";
            lblMessage.CssClass = "lblOk";
        }
        catch (Exception ex)
        {
            lblMessage.Text += "Si è verificato un errore irreversibile l'eliminazione da disco degli articoli: " + ex.Message;
            Utility.WriteLog("ERRORE", "lettura articoli da eliminare da disco", ex.Message, "", "");
            throw ex;
        }
        finally
        {
            if (objReader != null) objReader.Close();
        }
    }

    /// <summary>
    /// Versione modificata di lettura da file in cui il \n o \r da soli non vengono considerati come fine linea
    /// il metodo è piuttosto lento ma non ci sono alternative....
    /// </summary>
    /// <param name="rd"></param>
    /// <returns></returns>
    static private String readLine(StreamReader rd)
    {
        String toRet = null;
        char ch;
        try
        {
            while (true)
            {
                int val = rd.Read();
                if (val == -1) 
                    break;
                ch = Convert.ToChar(val);
                if (ch == '\r') 
                { 
                    rd.Read(); 
                    break; 
                }
                toRet += ch;
            }
        }
        catch (Exception) 
        { 
        
        }

        return toRet;
    }

}
